from sqlalchemy.orm import Session

from app.core.security import get_password_hash, verify_password
from app.models.user import User
from app.models.credit_transaction import CreditTransaction, TransactionType
from app.schemas.user import UserCreate

def get_user_by_id(db: Session, *, user_id: int) -> User | None:
    return db.query(User).filter(User.id == user_id).first()

def get_user_by_email(db: Session, *, email: str) -> User | None:
    return db.query(User).filter(User.email == email).first()


def get_user_by_username(db: Session, *, username: str) -> User | None:
    return db.query(User).filter(User.username == username).first()


def create_user(db: Session, *, user_in: UserCreate) -> User:
    db_user = User(
        email=user_in.email,
        username=user_in.username,
        hashed_password=get_password_hash(user_in.password),
        credits_balance=100  # Give new users 100 free credits
    )
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user

def authenticate_user(db: Session, *, email: str, password: str) -> User | None:
    user = get_user_by_email(db, email=email)
    if not user:
        return None
    if not verify_password(password, user.hashed_password):
        return None
    return user

def update_user_credits(
    db: Session, 
    *, 
    user_id: int, 
    amount: int, 
    trans_type: TransactionType, 
    description: str | None = None,
    job_id: int | None = None
) -> User:
    """
    Update user credits and create a transaction record.
    Amount can be positive (recharge, gift) or negative (fee).
    """
    db_user = db.query(User).filter(User.id == user_id).first()
    if not db_user:
        # This should not happen in a real scenario with protected routes
        raise ValueError("User not found")

    if amount < 0 and db_user.credits_balance < abs(amount):
        raise ValueError("Insufficient credits")

    db_user.credits_balance += amount

    transaction = CreditTransaction(
        user_id=user_id,
        amount=amount,
        type=trans_type,
        description=description,
        related_job_id=job_id
    )
    db.add(transaction)
    
    db.commit()
    db.refresh(db_user)
    return db_user
